#pragma once
#include <iostream>
#include <string>
#include <memory>
#include <mysql/mysql.h>
class MySQLHelper
{

public:
    using Ptr = std::shared_ptr<MySQLHelper>;

    MySQLHelper(const std::string &host, const std::string &user, const std::string& passwd, const std::string &dbname, int port)
    {
        _handler = mysql_init(nullptr);

        connect(host, user, passwd, dbname, port);;
    }

    bool connect(const std::string &host, const std::string &user, const std::string& passwd, const std::string &dbname, int port)
    {
        if (mysql_real_connect(_handler, host.c_str(), user.c_str(), passwd.c_str(), dbname.c_str(), port, nullptr, 0) == nullptr)
        {
            std::cout << "连接数据库错误，错误原因：" << mysql_error(_handler) << std::endl;
            close();
            return false;
        }

        return true;
    }


    // 需要传入一个携带std::vector<T>的数组引用为参数
    // 然后该函数就会将查询到的结果构造这样一个数组，作为参数调用用户传入的可调用对象
    template <typename Func>
    bool excuteSQL(const std::string &sql, Func &&exec)
    {
        if (mysql_query(_handler, sql.c_str()) != 0)
        {
            DLOG("执行sql语句 %s 失败，失败原因：%s", sql.c_str(), mysql_error(_handler));
            return false;
        }

        MYSQL_RES *result = mysql_store_result(_handler);
        if (result == nullptr)
        {
            std::cout << "查询语句获取结果集失败，失败原因：" << mysql_error(_handler) << std::endl;
            return false;
        }

        int num_fields = mysql_num_fields(result);
        MYSQL_ROW row;
        while ((row = mysql_fetch_row(result)))
        {
            std::vector<std::string> row_v;
            for (int i = 0; i < num_fields; i++)
            {
                if (row[i] != nullptr)
                    row_v.push_back(row[i]);
                else
                    row_v.push_back("");
            }
            std::forward<Func>(exec)(row_v);
        }
        mysql_free_result(result);
        return true;
    }

    bool excuteSQL(const std::string &sql)
    {
        if (mysql_query(_handler, sql.c_str()) != 0)
        {
            std::cout << "执行sql语句" << sql << "失败，" << "失败原因：" << mysql_error(_handler) << std::endl;
            // mysql_close(_handler);
            return false;
        }
        return true;
    }

    void close()
    {
        mysql_close(_handler);
    }

    ~MySQLHelper()
    {
        close();
    }

private:
    MYSQL *_handler;
};